package com.ferfalk.simplesearchviewexample;

import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.Image;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.PageSlider;
import ohos.agp.components.PageSliderProvider;
import ohos.agp.components.StackLayout;
import ohos.agp.components.TabList;
import ohos.agp.components.Text;
import ohos.agp.text.Font;
import ohos.agp.utils.LayoutAlignment;
import ohos.agp.window.dialog.PopupDialog;
import ohos.agp.window.service.WindowManager;
import ohos.bundle.AbilityInfo;
import ohos.global.resource.NotExistException;
import ohos.global.resource.WrongTypeException;
import ohos.security.SystemPermission;
import ohos.utils.PacMap;

import com.ferfalk.listener.PermissionListener;
import com.ferfalk.simplesearchview.SavedState;
import com.ferfalk.simplesearchview.SimpleSearchView;
import com.ferfalk.util.PermissionBridge;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

import static com.ferfalk.util.PermissionBridge.EVENT_PERMISSION_DENIED;
import static com.ferfalk.util.PermissionBridge.EVENT_PERMISSION_GRANTED;
import static ohos.bundle.IBundleManager.PERMISSION_GRANTED;

/**
 * 主界面
 *
 * @since 2021-04-16
 */
public class MainAbility extends Ability {
    private static final int PERMISSION_REQUEST_CODE = 1;
    private static final int DELAY_TIME = 1200;
    private static final int NEGATIVE_1 = -1;
    private static final int THREE = 3;

    Text mTitle;
    TabList mTabList;
    PageSlider mPageSlider;
    SimpleSearchView mSimpleSearchView;
    Image mSearch;
    DirectionalLayout mDlMenu;
    StackLayout mSlBar;

    SavedState mSavedState = new SavedState();

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        try {
            int color = getResourceManager().getElement(ResourceTable.Color_colorPrimaryDark).getColor();
            WindowManager.getInstance().getTopWindow().get().setStatusBarColor(color);
        } catch (IOException e) {
            e.getMessage();
        } catch (NotExistException e) {
            e.getMessage();
        } catch (WrongTypeException e) {
            e.getMessage();
        }
        mTitle = (Text) findComponentById(ResourceTable.Id_txt_title);
        mTitle.setFont(Font.DEFAULT_BOLD);
        initTabList();
        initPages();
    }

    @Override
    public void onSaveAbilityState(PacMap outState) {
        super.onSaveAbilityState(outState);
        mSavedState.setQuery((String) mSimpleSearchView.getQuery());
        mSavedState.setKeepQuery(mSimpleSearchView.isKeepQuery());
        mSavedState.setSearchOpen(mSimpleSearchView.isSearchOpen());
        outState.putSequenceableObject("savedState", mSavedState);
    }

    @Override
    public void onRestoreAbilityState(PacMap inState) {
        super.onRestoreAbilityState(inState);
        SavedState savedState = (SavedState) inState.getSequenceable("savedState").get();

        if (savedState != null) {
            mSimpleSearchView.setKeepQuery(savedState.isKeepQuery());
            getUITaskDispatcher().delayDispatch(() -> {
                if (savedState.isSearchOpen()) {
                    mSimpleSearchView.showSearch(true);
                    mSimpleSearchView.setQuery(savedState.getQuery(), false);
                }

                if (savedState.isMenuOpen()) {
                    showMenu();
                }
            }, DELAY_TIME);

            if (savedState.getSelectedTabIndex() != NEGATIVE_1 && savedState.getSelectedTabIndex() < THREE) {
                TabList.Tab tab = mTabList.getTabAt(savedState.getSelectedTabIndex());
                mTabList.selectTab(tab);
            }
        }
    }

    private void initTabList() {
        mSlBar = (StackLayout) findComponentById(ResourceTable.Id_toolbar_container);
        mTabList = (TabList) findComponentById(ResourceTable.Id_tab_list);
        TabList.Tab tabItem1 = mTabList.new Tab(getContext());
        tabItem1.setText("TAB 1");
        mTabList.addTab(tabItem1, true);

        TabList.Tab tabItem2 = mTabList.new Tab(getContext());
        tabItem2.setText("TAB 2");
        mTabList.addTab(tabItem2);

        TabList.Tab tabItem3 = mTabList.new Tab(getContext());
        tabItem3.setText("TAB 3");
        mTabList.addTab(tabItem3);

        mSearch = (Image) findComponentById(ResourceTable.Id_img_search);

        mSimpleSearchView = (SimpleSearchView) findComponentById(ResourceTable.Id_searchView);
        mSimpleSearchView.setAbility(this);
        mSimpleSearchView.setSearch(mSearch);
        mSimpleSearchView.setPermissionListener(new PermissionListener() {
            @Override
            public void onRequestPermission() {
                requestPermission();
            }
        });

        mDlMenu = (DirectionalLayout) findComponentById(ResourceTable.Id_dl_menu);
        mDlMenu.setClickedListener(component -> showMenu());
    }

    private void initPages() {
        // 从根页面布局的xml文件中获取到PageSlider
        mPageSlider = (PageSlider) findComponentById(ResourceTable.Id_container);

        List<Component> components = new ArrayList<>();
        Component component1 = LayoutScatter.getInstance(getContext())
            .parse(ResourceTable.Layout_tab_1_layout, null, false);
        Component component2 = LayoutScatter.getInstance(getContext())
            .parse(ResourceTable.Layout_tab_2_layout, null, false);
        Component component3 = LayoutScatter.getInstance(getContext())
            .parse(ResourceTable.Layout_tab_3_layout, null, false);
        components.add(component1);
        components.add(component2);
        components.add(component3);
        mPageSlider.setProvider(new PageProvider(this, components));
        mPageSlider.setOrientation(Component.HORIZONTAL);
        mPageSlider.setSlidingPossible(true);
        mPageSlider.addPageChangedListener(new PageSlider.PageChangedListener() {
            @Override
            public void onPageSliding(int itemPos, float itemPosOffset, int itemPosOffsetPixels) {
            }

            @Override
            public void onPageSlideStateChanged(int state) {
            }

            @Override
            public void onPageChosen(int itemPos) {
                mTabList.selectTab(mTabList.getTabAt(itemPos));
            }
        });
        mTabList.addTabSelectedListener(new TabListener(this, components, mPageSlider));
        mSimpleSearchView.setTabLayout(mTabList);
    }

    /**
     * request voice permission
     *
     */
    public void requestPermission() {
        List<String> permissions = new LinkedList<String>(Arrays.asList(
            SystemPermission.WRITE_USER_STORAGE,
            SystemPermission.READ_USER_STORAGE,
            SystemPermission.DISTRIBUTED_DATASYNC,
            SystemPermission.MICROPHONE));
        permissions.removeIf(
            permission ->
                verifySelfPermission(permission) == PERMISSION_GRANTED || !canRequestPermission(permission));

        if (!permissions.isEmpty()) {
            requestPermissionsFromUser(permissions.toArray(new String[permissions.size()]), PERMISSION_REQUEST_CODE);
        } else {
            PermissionBridge.getHandler().sendEvent(EVENT_PERMISSION_GRANTED);
        }
    }

    private void showMenu() {
        mSavedState.setMenuOpen(true);
        Component component = LayoutScatter.getInstance(getContext())
            .parse(ResourceTable.Layout_menu_pop_layout, null, false);
        PopupDialog popupDialog = new PopupDialog(getContext(), null);
        popupDialog.setCustomComponent(component);
        popupDialog.setDialogListener(() -> {
            mSavedState.setMenuOpen(false);
            popupDialog.destroy();
            return false;
        });
        component.setClickedListener(component2 -> {
            mSavedState.setMenuOpen(false);
            popupDialog.destroy();
        });

        int[] position = mSlBar.getLocationOnScreen();
        int x = mSlBar.getWidth() - component.getWidth();
        int y = position[1];
        popupDialog.showOnCertainPosition(LayoutAlignment.TOP, x, y);
    }

    /**
     * PageProvider的实现
     *
     * @since 2021-04-16
     */
    public class PageProvider extends PageSliderProvider {
        private static final String TAG = "Information";
        private Ability slice;

        private List<Component> tabComponents;

        /**
         * PageProvider constructor
         *
         * @param slice
         * @param tabComponents
         */
        public PageProvider(Ability slice, List<Component> tabComponents) {
            this.slice = slice;
            if (tabComponents != null) {
                this.tabComponents = tabComponents;
            } else {
                this.tabComponents = new ArrayList<>();
            }
        }

        @Override
        public int getCount() {
            return tabComponents.size();
        }

        @Override
        public Object createPageInContainer(ComponentContainer componentContainer, int position) {
            Component component = null;
            if (componentContainer == null) {
                return component;
            }
            if (0 <= position && position < tabComponents.size()) {
                component = tabComponents.get(position);
            }
            componentContainer.addComponent(component);
            return component;
        }

        @Override
        public void destroyPageFromContainer(ComponentContainer componentContainer, int position, Object obj) {
            if (componentContainer == null) {
                return;
            }
            if (obj instanceof Component) {
                componentContainer.removeComponent((Component) obj);
            }
        }

        @Override
        public boolean isPageMatchToObject(Component component, Object o) {
            return true;
        }
    }

    /**
     * TabListener的实现
     *
     * @since 2021-04-16
     */
    public class TabListener implements TabList.TabSelectedListener {
        private static final String TAG = "Information";
        private Ability slice;
        private List<Component> tabComponents;
        private PageSlider pageSlider;

        /**
         * TabListener constructor
         *
         * @param slice
         * @param tabComponents
         * @param pageSlider
         */
        public TabListener(Ability slice, List<Component> tabComponents, PageSlider pageSlider) {
            this.slice = slice;
            this.tabComponents = tabComponents;
            this.pageSlider = pageSlider;
        }

        @Override
        public void onSelected(TabList.Tab tab) {
            if (tab == null) {
                return;
            }
            if (pageSlider != null) {
                pageSlider.setCurrentPage(tab.getPosition());
                mSavedState.setSelectedTabIndex(tab.getPosition());
            }
        }

        @Override
        public void onUnselected(TabList.Tab tab) {
            if (tab == null) {
                return;
            }
        }

        @Override
        public void onReselected(TabList.Tab tab) {
        }
    }

    @Override
    protected void onBackPressed() {
        if (mSimpleSearchView.onBackPressed()) {
            return;
        }
        super.onBackPressed();
    }

    @Override
    protected void onStop() {
        super.onStop();
    }

    @Override
    public void onRequestPermissionsFromUserResult(int requestCode, String[] permissions, int[] grantResults) {
        if (requestCode != PERMISSION_REQUEST_CODE) {
            return;
        }
        for (int grantResult : grantResults) {
            if (grantResult != PERMISSION_GRANTED) {
                PermissionBridge.getHandler().sendEvent(EVENT_PERMISSION_DENIED);
                return;
            }
        }
        PermissionBridge.getHandler().sendEvent(EVENT_PERMISSION_GRANTED);
    }

    @Override
    protected void onOrientationChanged(AbilityInfo.DisplayOrientation displayOrientation) {
        super.onOrientationChanged(displayOrientation);
        mSimpleSearchView.onOrientationChanged(displayOrientation);
    }
}
